/**
 * $Id: SubmitMTThread.java,v 1.23 2006/11/06 07:01:41 martin Exp $
 *
 * Copyright 2006 Skyinfo, Inc. All Rights Reserved.
 */
package com.haoxi.gateway.runner;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.haoxi.gateway.common.CommonMsgBean;
import com.haoxi.gateway.common.Queue;
import com.haoxi.gateway.common.SQLConst;
import com.haoxi.gateway.common.SYSConst;
import com.haoxi.gateway.connector.Connector;
import com.haoxi.gateway.runner.smscommand.SubmitCmd;
import com.haoxi.gateway.util.db.DBConnectUtil;

/**
 * TODO
 * 
 * Revision History
 * 
 * 2006-5-25,star.Zhao,created it
 */
public class SubmitMTThread extends AbsOutQueue {
    private static final Log log = LogFactory.getLog(SubmitMTThread.class);
    private Map submitRespMap;
    private Connector conn;
    private static final String MY_NAME = "SubmitThread";
    private final int MAX_SLEEP_SECOND = 5;
    private int CURRENT_SLEEP_SECOND = 0;
    private Map sysCofn;

    public SubmitMTThread(Queue inQueue, Connector con, Map aMap) {
        super(inQueue);
        this.submitRespMap = aMap;
        this.conn = con;
        setName(MY_NAME);
        this.sysCofn = RunnerMgr.getInstance().getSystemConf();
        if (conn == null || submitRespMap == null) {
            log.error("SubmitThread init error (conn == null || submitRespMap == null)");
        }
    }

    public int doJob(Object pObject, int queueLen) {
        int nRet = AbsOutQueue.PROC_ERROR;
        if (pObject instanceof CommonMsgBean) {
            CommonMsgBean msgObj = (CommonMsgBean) pObject;
            Object cmd = msgObj.getReserve();
            if (cmd instanceof SubmitCmd) {
                SubmitCmd submitMtCmd = (SubmitCmd) cmd;
                //通道还未准备好，不进行发送，由其他MT通道发送
                if (conn.isClose()) {
                        log.error(conn.getConnName() + " is closed, current submitMT thread wait !!!");
                       return AbsOutQueue.PROC_RETRY;
                }
                // save Sended MT for need submitStatsu.
                String submitTime = SQLConst.dateformat.format(new Date());

                // limit the submit MT speed
                //SubmitAndGetMTConnDeamon.controlSubmitMTSpeed();
                if (null == sysCofn) {
                    sysCofn = RunnerMgr.getInstance().getSystemConf();
                }
                Object tmp = sysCofn.get(SYSConst.CONF_SUBMIT_SPEED);
                int submitSpeed = 20;
                if (null != tmp) {
                    submitSpeed = ((Integer) tmp).intValue();
                }
                try {
                    Thread.sleep(1000 / submitSpeed);
                } catch (InterruptedException io) {
                    log.error(io);
                }
                // 璁板綍涓嬪彂鏃堕棿
                submitMtCmd.setSubmitTime(submitTime);
                if (this.saveSendedMT(submitMtCmd)) {
                    try {
                        if (conn.writeProtcol(msgObj)) {
                            // record SendMT_NoResp_Count ++
                            if (conn.isResultCirrentCount()) {
                                CURRENT_SLEEP_SECOND = 0; // reset
                            }
                            conn.increaseSendMTNoRespCount();
                            nRet = AbsOutQueue.PROC_NORMAL;
                            log.debug("Send MT sucessfully! " + submitMtCmd.toString());
                        } else {
                            nRet = AbsOutQueue.PROC_RETRY;
                            log.error("Send MT unsucessfully" + submitMtCmd.toString());
                            this.deleteSendedMT(submitMtCmd.getSequence());

                        }
                    } catch (IOException e) {
                        this.deleteSendedMT(submitMtCmd.getSequence());
                        nRet = AbsOutQueue.PROC_RETRY;
                        log.error("send submit MT msg IOException:", e);
                    }
                    
                } else {
                    log.error("Send MT unsucessfully!" + submitMtCmd.toString());
                    nRet = AbsOutQueue.PROC_RETRY;
                }
            } else {
                // unkown object message !!!!!!!!!!!!!!!!!!!!!
                log.error("have unkown object message!");
                nRet = AbsOutQueue.PROC_ERROR;
            }
        } else {
            // unkown object message !!!!!!!!!!!!!!!!!!!!!
            log.error("have unkown object message!!");
            nRet = AbsOutQueue.PROC_ERROR;
        }
        return nRet;
    }

    /**
     * save Sended MT for need submitStatsu.
     * 
     * @param mt
     */
    private boolean saveSendedMT(SubmitCmd mt) {
        boolean result = false;
        // save NeedRespMTData into Mysql DB
        Connection conn = null;
        PreparedStatement ps = null;
        String gateway_DBName = (String) RunnerMgr.getInstance()
                .getSystemConf().get(SYSConst.CONF_DB_MYSQL);
        try {
                // put the NeedRespMTData into submitRespMap
                synchronized (submitRespMap) {
                submitRespMap.put(mt.getSequence(), mt);
            }

            conn = DBConnectUtil.open(gateway_DBName);
            ps = conn.prepareStatement(SQLConst.SAVE_NEED_SUBMITSTATUS_MTDATA);
            ps.setString(1, mt.getSequence());
            ps.setInt(2, mt.getStype());
            ps.setString(3, mt.getServiceId());
            ps.setString(4, mt.getOrgMobile());
            ps.setInt(5, mt.getOrgMobileType());
            ps.setString(6, mt.getDestMobile());
            ps.setInt(7, mt.getDestMobileType());
            ps.setString(8, mt.getFeeMobile());
            ps.setInt(9, mt.getFeeMobileType());
            ps.setString(10, mt.getFeeType());
            ps.setInt(11, mt.getFeeCode());
            ps.setString(12, mt.getMsgContent());
            ps.setInt(13, mt.getProvice());
            ps.setInt(14, mt.getCity());
            ps.setString(15, mt.getCityName());
            ps.setString(16, mt.getLinkID());
            ps.setInt(17, mt.getCp());
            ps.setString(18, mt.getSubmitTime());
            ps.setString(19, mt.getGateWayCode());
            ps.setString(20, mt.getSid());
            ps.setString(21, mt.getMomtRelateID());
            if (1 != ps.executeUpdate()) {
                log.error("Syncronize for add Sended MT data into MYsql DB Failed, MT's sequence: [" + mt.getSequence() + "]");
            }
            result = true;
        } catch (SQLException e) {
            result = false;
            log.error("SQLException:", e);
            log.error("Syncronize for add Sended MT data into MYsql DB Failed, MT's sequence: [" + mt.getSequence() + "]");
        } catch (Exception e) {
            result = false;
            log.error("other Exception:", e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                log.error("close:", e);
            }
        }
        return result;
    }

    /**
     * delete Sended MT for need submitStatsu.
     * 
     * @param mt
     */
    private void deleteSendedMT(String sequenceID) {
        if (null == sequenceID) {
            log.error("SubmitThread.deleteSendedMT() IlleagalArgument! ");
            return;
        }
        // put the NeedRespMTData into submitRespMap
        synchronized (submitRespMap) {
            log
            .error("SubmitThread.deleteSendedMT() delete MT , MT's sequence: ["
                    + sequenceID + "]");
            submitRespMap.remove(sequenceID);
        }
        // save NeedRespMTData into Mysql DB
        Connection conn = null;
        PreparedStatement ps = null;
        String gateway_DBName = (String) RunnerMgr.getInstance()
                .getSystemConf().get(SYSConst.CONF_DB_MYSQL);
        try {
            conn = DBConnectUtil.open(gateway_DBName);
            ps = conn
                    .prepareStatement(SQLConst.DELETE_NEED_SUBMITSTATUS_MTDATA);
            ps.setString(1, sequenceID);

            if (1 != ps.executeUpdate()) {
                log
                        .error("SubmitThread.deleteSendedMT() delete MT data into MYsql DB Failed, MT's sequence: ["
                                + sequenceID + "]");
            }
        } catch (SQLException e) {
            log.error("SQLException:", e);
            log
                    .error("SubmitThread.deleteSendedMT() delete MT data into MYsql DB Failed, MT's sequence: ["
                            + sequenceID + "]");
        } catch (Exception e) {
            log.error("other Exception:", e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                log.error("close:", e);
            }
        }
    }

}
